package org.needcoke.hs.signature;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.needcoke.hs.bean.InterceptRule;
import org.needcoke.hs.http.Request;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import javax.annotation.Resource;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

@Slf4j
@Service
public class DefaultSignatureInterceptor implements SignatureInterceptor {

    @Resource
    private Map<InterceptRule, Signature> signatureMap;

    @Override
    public void intercept(Request request) {
        Signature signature = getSignature(request.getPath(), request.agreement(), request.getHost(), request.getPort());
        if (null == signature) {
            return;
        }
        Map<String, String> urlParameter = request.getUrlParameter();
        signature.addParam(urlParameter);

        if (signature.isWithFormBody()) {
            Map<String, String> formParameter = request.getFormParameter();
            signature.addParam(formParameter);
        }

        if (signature.isWithApplicationBody()) {
            String body = request.getBody();
            signature.addApplicationBody(body);
        }

        String sign = signature.sign();
        /* 放置签名 */
        signature.preventSignature(request, sign);
    }


    private static final AntPathMatcher antPathMatcher = new AntPathMatcher();

    private Signature getSignature(String path, String agreement, String host, int port) {
        Set<InterceptRule> ruleSet = signatureMap.keySet();
        for (InterceptRule rule : ruleSet) {
            boolean match = true;
            if (StrUtil.isNotEmpty(rule.getPath())) {
                match = antPathMatcher.match(rule.getPath(), path);
            }
            if (StrUtil.isNotEmpty(rule.getAgreement())) {
                if (!rule.getAgreement().toLowerCase(Locale.ROOT).equals(agreement.toLowerCase(Locale.ROOT))) {
                    match = false;
                }
            }

            if (StrUtil.isNotEmpty(rule.getHost())) {
                if (!rule.getHost().equals(host)) {
                    match = false;
                }
            }
            if (0 == port) {
                port = 80;
            }
            if (StrUtil.isNotEmpty(rule.getPort())) {
                if (!rule.getPort().equals(String.valueOf(port))) {
                    match = false;
                }
            }

            if (match) {
                return signatureMap.get(rule);
            }
        }
        return null;
    }
}
